
#ifndef RECORD_H
#define RECORD_H

#include <stdio.h>
#include "TwoWayList.h"

enum Type {Int, Double, String};
class Schema;

#define PAGESIZE 2048

class Att {

	friend class IndexRecord;
private:

        char *data;
        int len;

public:

	Att ();
	~Att ();

	// these are some "extra" functions that I wrote to load/unload an attribute
	// they are pretty self-explanatory.  The only thing to be careful about is GetString,
	// which actually resutrs a COPY of the data in the attribute.  So you actually have to
	// deallocate the memory that it returns to you
	int LoadInt (int loadMe);
	int LoadDouble (double loadMe);
	int LoadString (char *loadMe);
	int GetInt ();
	double GetDouble ();
	char *GetString ();

	// gets the length of the attribute
	int GetLength ();

	// these are just like described in the assignment
	int ToBinary (char *here);
	int FromBinary (char *here);

};

class Record {

	friend class IndexRecord;
	friend class BPlusTree;
        Att *myData;
        int numAtts;
        int mySize;

public:

	// these either get the value or set the value in the record, for attribute i
	// just like for the attribute, these are pretty self-explanatory, except that
	// GetString actualy *copies* the value of the string, so you have to make sure
	// to free it when you are done
	int GetInt (int i);
	double GetDouble (int i);
	char *GetString (int i);
	void SetDouble (double in, int i);
	void SetInt (int in, int i);
	void SetString (char *in, int i);
	
	// Prints the record
	void Print (Schema &mySchema);

	// returns the length of the record
	int GetLength ();

	// these are all from the assignment
	Record ();
	~Record ();
	int FromBinary (char *here);
	int ToBinary (char *here);
	int SuckNextRecord (Schema &mySchema, FILE *textFile);
	void Consume (Record &fromMe);
};

class Page {

        TwoWayList <Record> myRecs;
        int numRecs;
        int curSizeInBytes;

public:

        // this takes a page and writes its binary representation to bits
        void ToBinary (char *bits);

        // this takes a binary representation of a page and gets the
        // records from it
        void FromBinary (char *bits);

        // the deletes the first record from a page and returns it; returns
        // a zero if there were no records on the page
        int GetFirst (Record &firstOne);

        // this appends the record to the end of a page.  The return value
        // is a one on success and a aero if there is no more space
        // note that the record is consumed so it will have no value after
        int Append (Record &addMe);

        // empty it out
        void EmptyItOut ();

        // constructor
        Page ();
        ~Page ();

};

class File {

        Page myBuff;
        int curLength;
        int curPos;
        int changed;
        int myFilDes;
        char *path;

public:

        // returns the current length of the file, in pages
        int GetLength ();

        // opens the given file; the first parameter tells whether or not to
        // create the file.  If the parameter is zero, a new file is created
        // the file; if notNew is zero, then the file is created and any other
        // file located at that location is erased.  Otherwise, the file is
        // simply opened
        void Open (int notNew, char *fName);

        // moves the record "pointer" in the file to the first record on
        // the specified page in the file
        void MovePointer (int whichPage);

        // gets the next record in the file; returns a 0 if there are no more
        // records and a 1 otherwise
        int NextRec (Record &getMe);

        // adds a new record to the very end of the file
        int Append (Record &addMe);

        // allows someone to explicitly get a specified page from the file
        int GetPage (Page &putItHere, int whichPage);

        // allows someone to explicitly write a specified page to the file
        // if the write is past the end of the file, all of the new pages that
        // are before the page to be written are zeroed out
        void AddPage (Page &addMe, int whichPage);

        // closes the file and returns the file length (in number of pages)
        int Close ();

        // closes the file and removes it from disk
        void Kill ();

        File ();
        ~File ();
};

struct AttSchema {
	Type myType;
	char *name;
};

class Schema {

        // gives the attributes in the schema
        int numAtts;
        AttSchema *myAtts;

	friend class Record; 

public:

	// get the type of the given attribute
	Type FindType (int i);

	// get the index of the given attribute
	int Find (char *attName);

	// just like in the assignment
	Schema (char *fName, char *relName);
	~Schema ();

};	


struct Op {
        int whichAtt;
        char compOp;
        Type hisType;
        Att literalVal;
};

class Predicate {

	Op *ops;
	int numOps;

public:

	~Predicate ();

	int Apply (Record &toMe);
	 Predicate (Schema &useMe, char *fName);
	
};

#endif

